package com.example.tweetfeed;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

import android.app.Fragment;

//Use fragment extension to prevent being destroyed on rotation
public class TwitterBearerToken extends Fragment{

	private static final String TWITTER_TOKEN_URL = "https://api.twitter.com/oauth2/token";
	private static final String TWITTER_LIMIT_URL = "https://api.twitter.com/1.1/application/rate_limit_status.json?resources=search";
	private static final String TWITTER_TOKEN_CONTENT_TYPE = "application/x-www-form-urlencoded;charset=UTF-8";
	
	private String mToken = "";
	private int mLimit = 0;
	private Date mReset = null;
	private String mAppName = "";
	private String mAppKey = "";
	
	public TwitterBearerToken(String appname, String apptoken) {
	//prevent destroy on rotation
		setRetainInstance(true);
	
		mAppName = appname;
		mAppKey = apptoken;
		mLimit = 0;
		
		regenerateToken();
	}
	
	public String getValue() {
	//check if we need to regenerate token before use it
		if(--mLimit <= 0 ||
			mReset.before(new Date())) {
			cronRegenTask(1);
		}
		return mToken;
	}
	
	private void cronRegenTask(int secs){
		Timer timer = new Timer();
		timer.schedule(new TimerTask() { 
	        public void run() 
	        { 
	        	regenerateToken();
	        } 
	    }, new Date(System.currentTimeMillis() + (secs * 1000)) );
	}
	
	private void regenerateToken() {
		mToken = getBearerToken();
	//if failed try again
		if(mToken == null) {
			cronRegenTask(1);
		}
	}
	
	private String getBearerToken() {
		String ret = null;
		try {
			HttpClient client = new DefaultHttpClient();
			HttpPost authpost = new HttpPost(TWITTER_TOKEN_URL);
			authpost.addHeader("User-Agent", mAppName);
			authpost.addHeader("Authorization", "Basic " + mAppKey);
			authpost.addHeader("Content-Type", TWITTER_TOKEN_CONTENT_TYPE);
			authpost.setEntity(new StringEntity("grant_type=client_credentials","UTF-8"));
			
			HttpResponse response = client.execute(authpost);
			if (response.getStatusLine().getStatusCode() == 200) {
				JSONObject json = getJsonContent(response);
                ret = json.getString("access_token");
                //setup limit
                setTokenLimit(ret);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}
	
	private int setTokenLimit(String tkn) {
		int ret = 0;
		try {
			HttpClient client = new DefaultHttpClient();
			HttpGet limitget = new HttpGet(TWITTER_LIMIT_URL);
			limitget.addHeader("User-Agent", mAppName);
			limitget.addHeader("Authorization", "Bearer " + tkn);
			
			HttpResponse response = client.execute(limitget);
			if (response.getStatusLine().getStatusCode() == 200) {
				JSONObject json =getJsonContent(response);
				mLimit = json.getJSONObject("resources").getJSONObject("search")
                		.getJSONObject("/search/tweets").getInt("remaining");
				int resetMilis = json.getJSONObject("resources").getJSONObject("search")
                		.getJSONObject("/search/tweets").getInt("reset");
				mReset = new Date(resetMilis);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}
	
	private JSONObject getJsonContent(HttpResponse response) throws Exception {
		InputStream content = response.getEntity().getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        
        String all = "", line = null;
        while ((line = reader.readLine()) != null) {
        	all += line;
        }
        return new JSONObject(all);
	}
}
